package com.translate.web.api.controller;

import java.util.List;
import java.util.Map;
import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;

import org.springframework.transaction.annotation.Transactional;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.context.request.NativeWebRequest;
import com.param.impl.IdPageParam;
import com.param.impl.IdParam;
import com.translate.vo.TeamVO;
import com.translate.vo.UserVO;
import com.translate.vo.contract.IUserVO;
import com.response.vo.ResponseModel;
import com.returns.value.ICodeAndData;
import com.controller.base.AbstractCommonController;
import com.msg.ResponseCode;
import com.page.PageResponseData;
import com.translate.web.param.TeamUpdateParam;
import com.translate.web.param.UserIdParam;
import com.translate.web.constant.RedisConstant;
import com.translate.web.constant.RedisExpireTime;
import com.translate.web.param.IdAndUserIdParam;
import com.translate.web.param.JoinTeamParam;
import com.translate.web.param.RefuseJoinTeam;
import com.translate.web.param.TeamAddBySearchParam;
import com.translate.web.param.TeamAddParam;
import com.translate.web.param.TeamSearchParam;
import com.translate.web.param.contract.IIdAndUserIdParam;
import com.translate.web.param.contract.ITeamAddParam;
import com.translate.web.param.contract.IUserIdParam;
import com.translate.entity.NoticeCenter;
import com.translate.entity.StaticsNum;
import com.translate.entity.Team;
import com.translate.entity.TeamAssoc;
import com.translate.entity.TeamInfo;
import com.translate.entity.User;
import com.translate.web.service.INoticeCenterService;
import com.translate.web.service.ITeamService;
import com.translate.web.service.IUserService;
import com.basic.service.contract.IBaseService;
import com.common.util.CopyEntity;
import com.common.util.ListConvertMap;
import com.common.util.MergeDataSource;

@RestController
@RequestMapping("team")
public class TeamController extends AbstractCommonController<Team, IdPageParam> {
	private ITeamService service;

	INoticeCenterService centerService;

	private IUserService userService;

	public TeamController(ITeamService service) {
		this.service = service;
	}

	@Resource
	public void setCenterService(INoticeCenterService centerService) {
		this.centerService = centerService;
	}

	protected long setCreateInfo(ITeamAddParam param, NativeWebRequest httpServletRequest) {
		long userId = this.getUserId(httpServletRequest);
		param.setUserId((int) userId);
		return userId;
	}

	@PostMapping("/teamInfo")
	public ResponseModel<TeamVO> teamInfo(NativeWebRequest httpServletRequest) {

		long userId = this.getUserId(httpServletRequest);

		IUserVO userDetails = this.userService.getUserDetails((int) userId, UserVO.class);

		if (null == userDetails) {
			return ResponseModel.<TeamVO>errorMsg(null, "获取用户信息失败");
		}

		IIdAndUserIdParam param = new IdAndUserIdParam();

		Integer teamId = userDetails.getTeamId();

		Byte status = userDetails.getStatus();

		paramParse(userId, param, teamId, status);

		String teamKey = RedisConstant.getTeamKey(userId);

		TeamVO dataByIdFromCache = this.service.getDataByIdFromCache(param, TeamVO.class, teamKey,
				RedisExpireTime.TEAM_DETAIL);

		if (null == dataByIdFromCache.getId()) {
			return ResponseModel.<TeamVO>success(null);
		}

		return ResponseModel.<TeamVO>success(dataByIdFromCache);
	}

	/**
	 * 处理参数
	 * @param userId
	 * @param param
	 * @param teamId
	 * @param status
	 */
	protected void paramParse(long userId, IIdAndUserIdParam param, Integer teamId, Byte status) {
		if (0 != teamId && 1 == status) {
			// 表示已经有团队了
			param.setId(teamId);
		} else {
			param.setUserId(userId);
			param.setId(0);
		}
	}

	@PostMapping("/staticsTeamInfo")
	public ResponseModel<List<StaticsNum>> staticsTeamInfo(@RequestBody @Validated IdParam param,
			NativeWebRequest httpServletRequest) {
		long userId = this.getUserId(httpServletRequest);

		User userInfoToCache = this.userService.getUserInfoToCache((int) userId);

		if (0 == userInfoToCache.getIsRegimental()) {
			return ResponseModel.<List<StaticsNum>>errorMsg(null, "您不是团长");
		}

		List<StaticsNum> staticsTeamInfo = this.userService.staticsTeamInfo(param.getId());

		return ResponseModel.<List<StaticsNum>>success(staticsTeamInfo);
	}

	/**
	 * 团队成员数量
	 * 
	 * @param httpServletRequest
	 * @return
	 */
	@PostMapping("/teamNumbers")
	public ResponseModel<List<TeamInfo>> teamNumbers(NativeWebRequest httpServletRequest) {

		long userId = this.getUserId(httpServletRequest);

		User userInfoToCache = userService.getUserInfoToCache((int) userId);

		Integer teamId = userInfoToCache.getTeamId();

		List<TeamInfo> groupNumAndApplyNum = userService.groupNumAndApplyNum(teamId);

		return ResponseModel.<List<TeamInfo>>success(groupNumAndApplyNum);
	}

	/**
	 * 搜索团队列表
	 * 
	 * @param <V>
	 * @param param
	 * @return
	 */
	@PostMapping("applyToJoin")
	public ResponseModel<List<TeamVO>> applyToJoin(@RequestBody @Validated TeamSearchParam param) {

		List<TeamVO> datasByIdFromCache = this.service.getTeamBySearch(param, TeamVO.class);

		if (0 == datasByIdFromCache.size()) {
			return ResponseModel.<List<TeamVO>>success(datasByIdFromCache);
		}

		int[] ids = datasByIdFromCache.stream().mapToInt(e -> e.getId()).toArray();

		List<TeamAssoc> teamAssocs = userService.getTeamAssocs(ids);

		Map<Integer, TeamAssoc> map = ListConvertMap.listToMap(teamAssocs, TeamAssoc::getTeamId);

		MergeDataSource<TeamVO> mergeDataSource = new MergeDataSource<TeamVO>(datasByIdFromCache);

		mergeDataSource.mergeRelease(TeamVO::getId, map, (TeamVO t, TeamAssoc v) -> {

			t.setNum(v.getNum());

			return t;
		});

		return ResponseModel.<List<TeamVO>>success(datasByIdFromCache);
	}

	@PostMapping("/joinTeam")
	@Transactional
	public ResponseModel<Integer> insert(@RequestBody @Validated JoinTeamParam param,
			NativeWebRequest httpServletRequest) {

		long userId = this.getUserId(httpServletRequest);
		param.setUserId(userId);

		Team dataDetailFromCache = service.selectByPrimaryKey(param.getId());

		if (dataDetailFromCache.getGroupName() == null) {
			return ResponseModel.<Integer>errorMsg(ResponseCode.ERROR.getCode(), "该团队不存在");
		}

		Byte status = dataDetailFromCache.getStatus();

		if (status == null) {
			return ResponseModel.<Integer>errorMsg(ResponseCode.ERROR.getCode(), "该团队不存在");
		}

		if (1 != status) {
			return ResponseModel.<Integer>errorMsg(ResponseCode.ERROR.getCode(), "该团队未审核或已拒绝");
		}
		int joinTeam = userService.joinTeam(param);
		
		// 发送申请通知 用户【ID12345678】申请加入团队，申请原因:希望加入团队:
		
		NoticeCenter center = new NoticeCenter();
		
		center.setJump((byte) 1);
		
		center.setUserId(dataDetailFromCache.getUserId());

		center.setNoticeContent("用户【" + userId + "】申请加入团队，申请原因:" + param.getReason());
		
		center.setNoticeType((byte) 3);
		
		center.setTitle("申请加入团队");
		
		center.setPlatform((byte) 0);
		
		center.setTypeId(param.getId());
		
		centerService.insert(center);

		return ResponseModel.<Integer>success(joinTeam);
	}

	/**
	 * 团队成员
	 */
	@PostMapping("/teamMembers")
	public ResponseModel<PageResponseData<UserVO>> insert(NativeWebRequest httpServletRequest) {

		IUserIdParam param = new UserIdParam();

		param.setUserId((int) this.getUserId(httpServletRequest));

		ICodeAndData<PageResponseData<UserVO>> codeAndData = userService.getTeamList(param, UserVO.class);

		if (codeAndData.getStatus() == ResponseCode.ERROR.getCode()) {
			return ResponseModel.<PageResponseData<UserVO>>errorMsg(null, codeAndData.getMsg());
		}

		return ResponseModel.success(codeAndData.getData());
	}

	/**
	 * 团队加入申请列表
	 * 
	 * @param <V>
	 * @param param
	 * @return
	 */
	@PostMapping("applyForList")
	public ResponseModel<PageResponseData<UserVO>> applyForList(NativeWebRequest httpServletRequest) {

		IUserIdParam param = new UserIdParam();

		param.setUserId((int) this.getUserId(httpServletRequest));

		ICodeAndData<PageResponseData<UserVO>> codeAndData = userService.applyForTeamList(param, UserVO.class);

		if (codeAndData.getStatus() == ResponseCode.ERROR.getCode()) {
			return ResponseModel.<PageResponseData<UserVO>>errorMsg(null, codeAndData.getMsg());
		}

		return ResponseModel.success(codeAndData.getData());
	}

	/**
	 * 通过
	 * 
	 * @param param
	 * @param httpServletRequest
	 * @return
	 */
	@PostMapping("/passThrough")
	public ResponseModel<Integer> passThrough(@RequestBody @Validated IdAndUserIdParam param,
			NativeWebRequest httpServletRequest) {

		param.setUserId(this.getUserId(httpServletRequest));

		ICodeAndData<Integer> codeAndData = this.userService.passThrough(param);

		if (codeAndData.getStatus() == ResponseCode.ERROR.getCode()) {
			return ResponseModel.errorMsg(null, codeAndData.getMsg());
		}
		return ResponseModel.success(codeAndData.getData());
	}

	/**
	 * 拒绝
	 * 
	 * @param param
	 * @param httpServletRequest
	 * @return
	 */
	@PostMapping("/refuse")
	@Transactional
	public ResponseModel<Integer> refuse(@RequestBody @Validated RefuseJoinTeam param,
			NativeWebRequest httpServletRequest) {

		long userId = this.getUserId(httpServletRequest);

		User userInfoToCache = this.userService.getUserInfoToCache((int) userId);

		if (1 != userInfoToCache.getIsRegimental()) {
			return ResponseModel.<Integer>errorMsg(ResponseCode.ERROR.getCode(), "您不是团长");
		}

		param.setUserId(userId);

		ICodeAndData<Integer> codeAndData = this.userService.refuse(param);

		if (codeAndData.getStatus() == ResponseCode.ERROR.getCode()) {
			return ResponseModel.errorMsg(null, codeAndData.getMsg());
		}

		NoticeCenter center = new NoticeCenter();

		Integer id = param.getId();

		center.setUserId(id);

		IIdAndUserIdParam idParam = new IdAndUserIdParam();

		Integer teamId = userInfoToCache.getTeamId();
		idParam.setId(teamId);

		idParam.setUserId(userId);

		Team dataDetailFromCache = this.service.getDataDetailFromCache(idParam, RedisConstant.getTeamKey(id), 1);

		center.setNoticeContent("【" + dataDetailFromCache.getGroupName() + "】团队已拒绝您的申请，审核原因:" + param.getRefuse());

		center.setPlatform((byte) 0);

		center.setTypeId(teamId);

		center.setNoticeType((byte) 3);

		center.setTitle("加入团队通知");

		centerService.insert(center);

		return ResponseModel.success(codeAndData.getData());
	}

	/**
	 * @param <V>
	 * @param param
	 * @return
	 */
	@PostMapping("/add")
	@Transactional
	public ResponseModel<Integer> insert(@RequestBody @Validated TeamAddParam param,
			NativeWebRequest httpServletRequest) {

		int userId = (int) this.getUserId(httpServletRequest);

		User userInfoToCache = this.userService.getUserInfoToCache((int) userId);

		if (1 == userInfoToCache.getStatus()) {
			return ResponseModel.errorMsg(null, "您已是团队成员，无法申请创立团队");
		}

		IIdAndUserIdParam userIdParam = new IdAndUserIdParam();

		userIdParam.setUserId(userId);

		userIdParam.setId(0);

		String teamKey = RedisConstant.getTeamKey(userId);

		Team selectByPrimaryKey = this.service.getDataDetailFromCache(userIdParam, teamKey, 6);

		int id = 0;

		setCreateInfo(param, httpServletRequest);

		try {
			do {
				if (null != selectByPrimaryKey) {

					Byte status = selectByPrimaryKey.getStatus();

					if (null == selectByPrimaryKey.getId()|| null == status) {
						break;
					}

					if (0 == status) {
						return ResponseModel.errorMsg(null, "在审核中");
					}

					if (1 == status) {
						return ResponseModel.errorMsg(null, "该团队已通过审核且已存在");
					}

					// 更新申请信息

					Team team = CopyEntity.copyEntity(param, Team.class);

					team.setId(selectByPrimaryKey.getId());

					team.setStatus((byte) 0);

					int res = this.service.updateByPrimaryKeySelective(team);

					return ResponseModel.<Integer>success(res);
				}
			} while (false);

			// 利用主键约束
			id = this.service.parseInsert(param, Team.class);
			
			// 发送创建团队通知
			// 张三(ID:12345678)申请创建【科研机构】团队，请及时查看处理!
			NoticeCenter noticeCenter = new NoticeCenter();
			
			noticeCenter.setUserId(userId);
			
			noticeCenter.setPlatform((byte) 1);
			
			noticeCenter.setJump((byte) 0);
			
			noticeCenter.setNoticeContent(userInfoToCache.getRealname()+"(ID:" + userId +"申请创建【"+param.getGroupName()+"】团队，请及时处理！");
			
			noticeCenter.setNoticeType((byte) 3);
			
			noticeCenter.setTypeId(id);
			
			noticeCenter.setTitle("团队签约申请");
			
			noticeCenter.setAdminId(0);
			
			centerService.insert(noticeCenter);
			
		} catch (Exception e) {
			e.printStackTrace();
			return ResponseModel.errorMsg(null, "【已申请过，后台正在审核】或邮箱不能重复或已存在该团队");
		}
		return ResponseModel.<Integer>success(id);
	}

	@PostMapping("/addTeamMember")
	@Transactional
	public ResponseModel<Integer> addTeamMember(@RequestBody @Validated TeamAddBySearchParam param,
			NativeWebRequest httpServletRequest) {

		param.setUserId(this.getUserId(httpServletRequest));

		ICodeAndData<Integer> codeAndData = this.userService.addTeamMember(param);

		if (codeAndData.getStatus() == ResponseCode.ERROR.getCode()) {
			return ResponseModel.errorMsg(null, codeAndData.getMsg());
		}
		return ResponseModel.success(codeAndData.getData());
	}

	/**
	 * 退出团队
	 * 
	 * @param nativeWebRequest
	 * @return
	 */
	@PostMapping("/exitTeam")
	public ResponseModel<Integer> exitTeam(NativeWebRequest nativeWebRequest) {

		long userId = this.getUserId(nativeWebRequest);

		User userInfoToCache = this.userService.getUserInfoToCache((int) userId);

		ICodeAndData<Integer> codeAndData = this.userService.exitTeam((int) userId);

		if (codeAndData.getStatus() == ResponseCode.ERROR.getCode()) {
			return ResponseModel.errorMsg(null, codeAndData.getMsg());
		}

		// 【团队名称】已将您移出团队，很遗憾无法继续为您提供团队服务。

		NoticeCenter center = new NoticeCenter();

		center.setUserId((int) userId);

		IIdAndUserIdParam idParam = new IdAndUserIdParam();

		Integer teamId = userInfoToCache.getTeamId();
		idParam.setId(teamId);

		Team dataDetailFromCache = this.service.getDataDetailFromCache(idParam, RedisConstant.getTeamKey(teamId), 1);

		// 您已退出【团队名称】团队，很速憾无法继续为您提供团队服务。
		center.setNoticeContent("您已退出【" + dataDetailFromCache.getGroupName() + "】团队，很遗憾无法继续为您提供团队服务");

		center.setPlatform((byte) 0);

		center.setNoticeType((byte) 3);

		center.setTitle("退出团队通知");

		center.setTypeId(dataDetailFromCache.getId());

		centerService.insert(center);

		return ResponseModel.success(codeAndData.getData());
	}

	/**
	 * 取消申请
	 * 
	 * @param nativeWebRequest
	 * @return
	 */
	@PostMapping("/applyForCancel")
	public ResponseModel<Integer> applyForCancel(NativeWebRequest nativeWebRequest) {

		return ResponseModel.success(this.service.deleteByUserId((int) this.getUserId(nativeWebRequest)));
	}

	/**
	 * 移除团队成员
	 * 
	 * @param param
	 * @param httpServletRequest
	 * @return
	 */
	@PostMapping("/removeMemberByTeam")
	@Transactional
	public ResponseModel<Integer> removeMemberByTeam(@RequestBody @Validated IdAndUserIdParam param,
			NativeWebRequest httpServletRequest) {

		long userId = this.getUserId(httpServletRequest);
		param.setUserId(userId);

		ICodeAndData<Integer> codeAndData = this.userService.removeMemberByTeam(param);

		if (codeAndData.getStatus() == ResponseCode.ERROR.getCode()) {
			return ResponseModel.errorMsg(null, codeAndData.getMsg());
		}

		// 【团队名称】已将您移出团队，很遗憾无法继续为您提供团队服务。

		NoticeCenter center = new NoticeCenter();

		Integer id = param.getId();

		center.setUserId(id);

		IIdAndUserIdParam idParam = new IdAndUserIdParam();

		idParam.setId(codeAndData.getData());

		Team dataDetailFromCache = this.service.getDataDetailFromCache(idParam, RedisConstant.getTeamKey(id), 1);

		center.setNoticeContent("【" + dataDetailFromCache.getGroupName() + "】已将您移出团队，很遗憾无法继续为您提供团队服务");

		center.setPlatform((byte) 0);

		center.setNoticeType((byte) 3);

		center.setTitle("退出团队通知");

		center.setTypeId(dataDetailFromCache.getId());

		centerService.insert(center);

		return ResponseModel.success(codeAndData.getData());

	}

	@Override
	protected IBaseService<Team> getBaseService() {
		return this.service;
	}

	/**
	 * 添加
	 * 
	 * @param <V>
	 * @param param
	 * @return
	 */
	@PostMapping("/update")
	public ResponseModel<Integer> update(@Validated @RequestBody TeamUpdateParam param,
			HttpServletRequest httpServletRequest) {
		int res = this.service.parseUpdate(param, Team.class);
		return ResponseModel.<Integer>success(res);
	}

	protected <VO> Class<VO> getTarget() {
		return (Class<VO>) TeamVO.class;
	}

	@Resource
	public void setUserService(IUserService userService) {
		this.userService = userService;
	}
}
